home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oh!X 2000 Spring
/
Oh!X 2000 Spring Special CD-ROM (Japan) (Part 1).7z
/
Oh!X 2000 Spring Special CD-ROM (Japan) (Part 1).bin
/
MIPSSIM
/
dis.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-12-02
|
54KB
|
1,871 lines
#include <stdio.h>
#include "define.h"
#define BigEndian 0
#define LittleEndian 1
#define MIPS1 0
#define MIPS3 1
#define MIPS16 2
#define MIPS4 3
static char insn_buf[256];
static int ty_mips = MIPS4;
static int endian = LittleEndian;
static ulong saddr = 0;
static ulong opcode;
static void dis_init(void);
static void dis_cp1(int,int,int,int,int,ulong);
static void dis_special(int,int,int,int,int,int,ulong,ulong);
static void dis_bcond(int,int,int,int,int,int,ulong,ulong);
static void dis_copz(int,int,int,int,int,int,int,ulong,ulong);
static void dis_cop1x(int,int,int,int,int,int,ulong,ulong);
static void dis_cache(int,int,int,long,ulong);
static void dis_mips(ulong,ulong);
static int mips16_reg_get(int);
static void dis_mips16_RR(ulong,ulong,ulong,ulong,ulong);
static void dis_mips16_extend(ulong,ulong);
static void dis_mips16(ulong,ulong);
void dis_one(ulong hi, ulong lo)
{
int err;
opcode = get_icache(hi, lo, &err);
dis_mips(opcode, lo);
}
void dis16_one(ulong hi, ulong lo)
{
int err;
opcode = get_icache(hi,lo,&err);
if(lo&3)
opcode = (opcode>>16)&0xffff;
else
opcode = opcode&0xffff;
dis_mips16(opcode, lo);
}
void dismips(char *base, char *num)
{
int cnt;
if(*base!='\0')
saddr = (ulong)gen_val(base);
if(*num=='\0')
cnt = 20;
else
cnt = (int)gen_val(num);
dis_init();
do{
dis_one(sign_extend(saddr), saddr);
saddr += 4;
}while(--cnt);
}
void dismips16(char *base, char *num)
{
int cnt;
if(*base!='\0')
saddr = (ulong)gen_val(base);
if(*num=='\0')
cnt = 20;
else
cnt = (int)gen_val(num);
dis_init();
do{
dis16_one(sign_extend(saddr),saddr);
saddr += 2;
}while(--cnt);
}
/*********************************************************************/
static char *regn_1[]={
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10","r11","r12","r13","r14","r15",
"r16","r17","r18","r19","r20","r21","r22","r23",
"r24","r25","r26","r27","r28","r29","r30","r31"
};
static char *regn_2[]={
"$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
"$8", "$9", "$10","$11","$12","$13","$14","$15",
"$16","$17","$18","$19","$20","$21","$22","$23",
"$24","$25","$26","$27","$28","$29","$30","$31"
};
static char *cregn_1[]={
"C0_Index", "C0_Random", "C0_EntryLo", "cp0reg03",
"C0_Context", "cp0reg5", "cp0reg6", "cp0reg7",
"C0_BadVAddr", "cp0reg9", "C0_EntryHi", "cp0reg11",
"C0_SR", "C0_Cause", "C0_EPC", "C0_Prid",
"cp0reg16", "cp0reg17", "cp0reg18", "cp0reg19",
"cp0reg20", "cp0reg21", "cp0reg22", "cp0reg23",
"cp0reg24", "cp0reg25", "cp0reg26", "cp0reg27",
"cp0reg28", "cp0reg29", "cp0reg30", "cp0reg31"
};
static char *cregn_2[]={
"C0_Index", "C0_Random", "C0_EntryLo0", "C0_EntryLo1",
"C0_Context", "C0_PageMask", "C0_Wired", "cp0reg7",
"C0_BadVAddr", "C0_Count", "C0_EntryHi", "C0_Compare",
"C0_SR", "C0_Cause", "C0_EPC", "C0_Prid",
"C0_Config", "C0_LLAddr", "C0_WatchLo", "C0_WatchHi",
"C0_XContext", "cp0reg21", "cp0reg22", "cp0reg23",
"cp0reg24", "cp0reg25", "C0_ECC", "C0_CacheErr",
"C0_TagLo", "C0_TagHi", "C0_ErrorEPC", "cp0reg31",
};
char **regn =regn_1;
char **cregn=cregn_2;
static char *jnam[] ={"j","jal"};
static char *bnam[] ={"beq","bne","blez","bgtz"};
static char *inam[] ={"addi","addiu","slti","sltiu","andi","ori","xori"};
static char *lsnam[]={"lb","lh","lwl","lw","lbu","lhu","lwr","lwu","sb","sh","swl","sw","sdl","sdr","swr"};
static char *snum[] ={"sll","","srl","sra","sllv","","srlv","srav"};
static char *mdnam[]={"mult","multu","div","divu"};
static char *anam[] ={"add","addu","sub","subu","and","or","xor","nor","","","slt","sltu"};
static char *tnam[] ={"tge","tgeu","tlt","tltu","teq","","tne",""};
static char *fnam[]={
"add", "sub", "mul", "div", "sqrt", "abs", "mov", "neg",
"round.l","trunc.l","ceil.l","floor.l","round.w","trunc.w","ceil.w","floor.w",
"", "movt", "movz", "movn", "", "recip", "rsqrt", "",
"", "", "", "", "", "", "", "",
"cvt.s","cvt.d","", "", "cvt.w","cvt.l","", "",
"", "", "", "", "", "", "", "",
"c.f", "c.un", "c.eq", "c.ueq","c.olt","c.ult","c.ole","c.ule",
"c.sf", "c.ngle","c.seq","c.ngl","c.lt","c.nge","c.le", "c.ngt"
};
static char *macc_nam[]={"madd","msub","nmadd","nmsub"};
static char *pref_hint[]={
"load",
"store",
"",
"",
"load_streamed",
"store_streamed",
"load_retained",
"store_retained",
"","","","","","","","","","","","","","","","","",
"writeback_invalidate"
};
static void dis_init(void)
{
regn = regn_1;
if(ty_mips==MIPS1)
cregn = cregn_1;
else
cregn = cregn_2;
if(ty_mips==MIPS16)
saddr &= 0xfffffffe;
else
saddr &= 0xfffffffc;
}
static void dis_cp1(int fmt,int ft,int fs,int fd,int func,ulong pc)
{
ulong temppc;
int immd;
immd = (fs<<11)|(fd<<6)|func;
if(immd&0x8000){
immd |=0xffff0000;
temppc=(immd<<2);
}
else temppc=immd<<2;
temppc=(pc+4)+temppc;
if((fnam[func&0x3f][0])&&(fmt&0x10)){
switch(func&0x38){
case 000: /* operation */
if((func&7)<4){
sprintf(insn_buf,"%s.%c\tfp%d,fp%d,fp%d\n",
fnam[func],(fmt&1)? 'd':'s',fd&0x1f,fs&0x1f,ft&0x1f);
}
else{
sprintf(insn_buf,"%s.%c\tfp%d,fp%d\n",
fnam[func],(fmt&1)? 'd':'s',fd&0x1f,fs&0x1f);
}
break;
case 020:
if((func&7)<2)
sprintf(insn_buf,"%s.%c\tfp%d,fp%d,cc%d\n",
(ft&1)? "movt" : "movf",
(fmt&1)? 'd':'s',
fd&0x1f,fs&0x1f,(ft>>2)&7);
else if((func&7)<4)
sprintf(insn_buf,"%s.%c\tfp%d,fp%d,%s\n",
fnam[func],(fmt&1)? 'd':'s',fd&0x1f,fs&0x1f,regn[ft&0x1f]);
else
sprintf(insn_buf,"%s.%c\tfp%d,fp%d\n",
fnam[func],(fmt&1)? 'd':'s',fd&0x1f,fs&0x1f);
break;
case 010: /* convert to integer */
case 040: /* convert */
sprintf(insn_buf,"%s.%c\tfp%d,fp%d\n",
fnam[func],(fmt&1)? ((fmt&4)?'l':'d')
: ((fmt&4)?'w':'s'),fd&0x1f,fs&0x1f);
break;
case 060: /* c */
case 070:
if(ty_mips==MIPS4)
sprintf(insn_buf,"%s.%c\tcc%d,fp%d,fp%d\n",
fnam[func],(fmt&1)? 'd':'s',(fd>>2)&7,fs&0x1f,ft&0x1f);
else
sprintf(insn_buf,"%s.%c\tfp%d,fp%d\n",
fnam[func],(fmt&1)? 'd':'s',fs&0x1f,ft&0x1f);
break;
}
}
else{
switch(fmt&0xf){
case 000:/* MF */
sprintf(insn_buf,"mfc1\t%s,fp%d\n",regn[ft],fs&0x1f);
break;
case 001:/* DMF */
sprintf(insn_buf,"dmfc1\t%s,fp%d\n",regn[ft],fs&0x1f);
break;
case 002:/* CF */
if((fs&0x1f)==31)
sprintf(insn_buf,"cfc1\t%s,C1_SR\n",regn[ft]);
else
sprintf(insn_buf,"cfc1\t%s,C1_Reg%d\n",regn[ft],fs&0x1f);
break;
case 004:/* MT */
sprintf(insn_buf,"mtc1\t%s,fp%d\n",regn[ft],fs&0x1f);
break;
case 005:/* DMT */
sprintf(insn_buf,"dmtc1\t%s,fp%d\n",regn[ft],fs&0x1f);
break;
case 006:/* CT */
if((fs&0x1f)==31)
sprintf(insn_buf,"ctc1\t%s,C1_SR\n",regn[ft]);
else
sprintf(insn_buf,"ctc1\t%s,C1_Reg%d\n",regn[ft],fs&0x1f);
break;
case 010:/* BC */
if((ft&3)==0){
if(ty_mips==MIPS4)
sprintf(insn_buf,"bc1f\tcc%d,0x%08x\n",(ft>>2)&7,(long)temppc);
else
sprintf(insn_buf,"bc1f\t0x%08x\n",(long)temppc);
}
else if((ft&3)==1){
if(ty_mips==MIPS4)
sprintf(insn_buf,"bc1t\tcc%d,0x%08x\n",(ft>>2)&7,(long)temppc);
else
sprintf(insn_buf,"bc1t\t0x%08x\n",(long)temppc);
}
else if((ft&3)==2){
if(ty_mips==MIPS4)
sprintf(insn_buf,"bc1fl\tcc%d,0x%08x\n",(ft>>2)&7,(long)temppc);
else
sprintf(insn_buf,"bc1fl\t0x%08x\n",(long)temppc);
}
else if((ft&3)==3){
if(ty_mips==MIPS4)
sprintf(insn_buf,"bc1tl\tcc%d,0x%08x\n",(ft>>2)&7,(long)temppc);
else
sprintf(insn_buf,"bc1tl\t0x%08x\n",(long)temppc);
}
else
sprintf(insn_buf,".word\t0x%08x\n",(long)opcode);
break;
default:
sprintf(insn_buf,".word\t0x%08x\n",(long)opcode);
}
}
}
static void dis_special(int rs,int rt,int rd,int sa,int func,int immd,ulong targ,ulong pc)
{
switch(func){
case 000:/* SLL */
case 002:/* SRL */
case 003:/* SRA */
sprintf(insn_buf,"%s\t%s,%s,%d\n",snum[func],regn[rd],regn[rt],sa);
break;
case 001:/* MOVT/MOVF */
sprintf(insn_buf,"%s\t%s,%s,cc%d\n",
(rt&1)? "movt" : "movf",
regn[rd],regn[rs],(rt>>2)&7);
break;
case 004:/* SLLV */
case 006:/* SRLV */
case 007:/* SRAV */
sprintf(insn_buf,"%s\t%s,%s,%s\n",snum[func],regn[rd],regn[rt],regn[rs]);
break;
case 010:/* JR */
sprintf(insn_buf,"jr\t%s\n",regn[rs]);
break;
case 011:/* JALR */
sprintf(insn_buf,"jalr\t%s,%s\n",regn[rd],regn[rs]);
break;
case 012:/* MOVZ */
case 013:/* MOVN */
sprintf(insn_buf,"%s\t%s,%s,%s\n",
(func==012)? "movz" : "movn",
regn[rd],regn[rs],regn[rt]);
break;
case 014:/* SYSCALL */
sprintf(insn_buf,"syscall\t%d\n",(rs<<15)|(rt<<10)|(rd<<5)|sa);
break;
case 015:/* BREAK */
sprintf(insn_buf,"break\t%d\n",(rs<<15)|(rt<<10)|(rd<<5)|sa);
break;
case 017:
sprintf(insn_buf,"sync\n");
break;
case 020:/* MFHI */
sprintf(insn_buf,"mfhi\t%s\n",regn[rd]);
break;
case 021:/* MTHI */
sprintf(insn_buf,"mthi\t%s\n",regn[rs]);
break;
case 022:/* MFLO */
sprintf(insn_buf,"mflo\t%s\n",regn[rd]);
break;
case 023:/* MTLO */
sprintf(insn_buf,"mtlo\t%s\n",regn[rs]);
break;
case 024:/* DSLLV */
case 026:/* DSRLV */
case 027:/* DSRAV */
sprintf(insn_buf,"d%s\t%s,%s,%s\n",snum[func-020],regn[rd],regn[rt],regn[rs]);
break;
case 030:/* MULT */
case 031:/* MULTU */
case 032:/* DIV */
case 033:/* DIVU */
sprintf(insn_buf,"%s\t%s,%s\n",mdnam[func-030],regn[rs],regn[rt]);
break;
case 034:/* DMULT */
case 035:/* DMULTU */
case 036:/* DDIV */
case 037:/* DDIVU */
sprintf(insn_buf,"d%s\t%s,%s\n",mdnam[func-034],regn[rs],regn[rt]);
break;
case 040:/* ADD */
case 041:/* ADDU */
case 042:/* SUB */
case 043:/* SUBU */
case 044:/* AND */
case 045:/* OR */
case 046:/* XOR */
case 047:/* NOR */
case 052:/* SLT */
case 053:/* SLTU */
sprintf(insn_buf,"%s\t%s,%s,%s\n",anam[func-040],regn[rd],regn[rs],regn[rt]);
break;
case 054:/* DADD */
case 055:/* DADDU */
case 056:/* DSUB */
case 057:/* DSUBU */
sprintf(insn_buf,"d%s\t%s,%s,%s\n",anam[func-054],regn[rd],regn[rs],regn[rt]);
break;
case 060:/* TGE */
case 061:/* TGEU */
case 062:/* TLT */
case 063:/* TLTU */
case 064:/* TEQ */
case 066:/* TNE */
sprintf(insn_buf,"%s\t%s,%s\n",tnam[func-060],regn[rs],regn[rt]);
break;
case 070:/* DSLL */
case 072:/* DSRL */
case 073:/* DSRA */
sprintf(insn_buf,"d%s\t%s,%s,%d\n",snum[func-070],regn[rd],regn[rt],sa);
break;
case 074:/* DSLL32 */
case 076:/* DSRL32 */
case 077:/* DSRA32 */
sprintf(insn_buf,"d%s32\t%s,%s,%d\n",snum[func-074],regn[rd],regn[rt],sa);
break;
case 050:/* MACC */
switch(sa){
case 0x00:
sprintf(insn_buf,"macc\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x01:
sprintf(insn_buf,"maccu\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x08:
sprintf(insn_buf,"macch\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x09:
sprintf(insn_buf,"macchu\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x10:
sprintf(insn_buf,"maccs\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x11:
sprintf(insn_buf,"maccus\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x18:
sprintf(insn_buf,"macchs\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x19:
sprintf(insn_buf,"macchus\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
default:
sprintf(insn_buf,".word\t0x%08x\n",opcode);
}
break;
case 051:/* DMACC */
switch(sa){
case 0x00:
sprintf(insn_buf,"dmacc\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x01:
sprintf(insn_buf,"dmaccu\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x08:
sprintf(insn_buf,"dmacch\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x09:
sprintf(insn_buf,"dmacchu\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x10:
sprintf(insn_buf,"dmaccs\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x11:
sprintf(insn_buf,"dmaccus\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x18:
sprintf(insn_buf,"dmacchs\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 0x19:
sprintf(insn_buf,"dmacchus\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
default:
sprintf(insn_buf,".word\t0x%08x\n",opcode);
}
break;
default:
sprintf(insn_buf,".word\t0x%08x\n",opcode);
}
}
static void dis_bcond(int rs,int rt,int rd,int sa,int func,int immd,ulong targ,ulong pc)
{
ulong temppc;
if(immd&0x8000){
immd |=0xffff0000;
temppc=(immd<<2);
}
else temppc=immd<<2;
temppc=(pc+4)+temppc;
switch(rt){
case 000:/* BLTZ */
sprintf(insn_buf,"bltz\t%s,0x%08x\n",regn[rs],(long)temppc);
break;
case 001:/* BGEZ */
sprintf(insn_buf,"bgez\t%s,0x%08x\n",regn[rs],(long)temppc);
break;
case 002:/* BLTZL */
sprintf(insn_buf,"bltzl\t%s,0x%08x\n",regn[rs],(long)temppc);
break;
case 003:/* BGEZL */
sprintf(insn_buf,"bgezl\t%s,0x%08x\n",regn[rs],(long)temppc);
break;
case 010:/* TGEI */
sprintf(insn_buf,"tgei\t%s,0x%04x\n",regn[rs],immd&0xffff);
break;
case 011:/* TGEIU */
sprintf(insn_buf,"tgeiu\t%s,0x%04x\n",regn[rs],immd&0xffff);
break;
case 012:/* TLTI */
sprintf(insn_buf,"tlti\t%s,0x%04x\n",regn[rs],immd&0xffff);
break;
case 013:/* TLTIU */
sprintf(insn_buf,"tltiu\t%s,0x%04x\n",regn[rs],immd&0xffff);
break;
case 014:/* TEQI */
sprintf(insn_buf,"teqi\t%s,0x%04x\n",regn[rs],immd&0xffff);
break;
case 016:/* TNEI */
sprintf(insn_buf,"tnei\t%s,0x%04x\n",regn[rs],immd&0xffff);
break;
case 020:/* BLTZAL */
sprintf(insn_buf,"bltzal\t%s,0x%08x\n",regn[rs],(long)temppc);
break;
case 021:/* BGEZAL */
sprintf(insn_buf,"bgezal\t%s,0x%08x\n",regn[rs],(long)temppc);
break;
case 022:/* BLTZALL */
sprintf(insn_buf,"bltzall\t%s,0x%08x\n",regn[rs],(long)temppc);
break;
case 023:/* BGEZALL */
sprintf(insn_buf,"bgezall\t%s,0x%08x\n",regn[rs],(long)temppc);
break;
default:
sprintf(insn_buf,".word\t0x%08x\n",(long)opcode);
}
}
static void dis_cop1x(int rs,int rt,int rd,int sa,int func,int immd,ulong targ,ulong pc)
{
switch(func){
case 000:
sprintf(insn_buf,"lwxc1\tfp%d,%s(%s)\n",rd,regn[rt],regn[rs]);
break;
case 001:
sprintf(insn_buf,"ldxc1\tfp%d,%s(%s)\n",rd,regn[rt],regn[rs]);
break;
case 010:
sprintf(insn_buf,"swxc1\tfp%d,%s(%s)\n",rd,regn[rt],regn[rs]);
break;
case 011:
sprintf(insn_buf,"sdxc1\tfp%d,%s(%s)\n",rd,regn[rt],regn[rs]);
break;
case 017:
if(((rd>=0)&&(rd<=7))||(rd==25))
sprintf(insn_buf,"prefx\t%s,%s(%s)\n",pref_hint[rd],regn[rt],regn[rs]);
else
sprintf(insn_buf,"prefx\t%d,%s(%s)\n",rd,regn[rt],regn[rs]);
break;
case 040:
case 041:
case 050:
case 051:
case 060:
case 061:
case 070:
case 071:
sprintf(insn_buf,"%s.%c\tfp%d,fp%d,fp%d,fp%d\n",
macc_nam[(func>>3)-4],
(func&1)? 'd' : 's',
sa,rs,rd,rt);
break;
default:
sprintf(insn_buf,".word\t0x%08x\n",opcode);
}
}
static void dis_copz(int cn,int rs,int rt,int rd,int sa,int func,int immd,ulong targ,ulong pc)
{
ulong temppc;
if(immd&0x8000) temppc=0xfffc|(immd<<2);
else temppc=immd<<2;
temppc=(pc+4)+temppc;
if(cn==0){/* COP0 */
switch(rs){
case 000:/* MF */
sprintf(insn_buf,"mfc0\t%s,%s\n",regn[rt],cregn[rd]);
break;
case 001:/* DMF */
sprintf(insn_buf,"dmfc0\t%s,%s\n",regn[rt],cregn[rd]);
break;
case 002:/* CF */
sprintf(insn_buf,"cfc0\t%s,%s\n",regn[rt],cregn[rd]);
break;
case 004:/* MT */
sprintf(insn_buf,"mtc0\t%s,%s\n",regn[rt],cregn[rd]);
break;
case 005:/* DMT */
sprintf(insn_buf,"dmtc0\t%s,%s\n",regn[rt],cregn[rd]);
break;
case 006:/* CT */
sprintf(insn_buf,"ctc0\t%s,%s\n",regn[rt],cregn[rd]);
break;
case 010:/* BC */
if(rt==0)
sprintf(insn_buf,"bc0f\t0x%08x\n",(long)temppc);
else if(rt==1)
sprintf(insn_buf,"bc0t\t0x%08x\n",(long)temppc);
else if(rt==2)
sprintf(insn_buf,"bc0fl\t0x%08x\n",(long)temppc);
else if(rt==3)
sprintf(insn_buf,"bc0tl\t0x%08x\n",(long)temppc);
else
sprintf(insn_buf,".word\t0x%08x\n",(long)opcode);
break;
case 020:
case 021:
case 022:
case 023:
case 024:
case 025:
case 026:
case 027:
case 030:
case 031:
case 032:
case 033:
case 034:
case 035:
case 036:
case 037:/* CO */
switch(func){
case 001:/* TLBR */
sprintf(insn_buf,"tlbr\n"); break;
case 002:/* TLBWI */
sprintf(insn_buf,"tlbwi\n"); break;
case 006:/* TLBWR */
sprintf(insn_buf,"tlbwr\n"); break;
case 010:/* TLBP */
sprintf(insn_buf,"tlbp\n"); break;
case 020:/* RFE */
sprintf(insn_buf,"rfe\n"); break;
case 030:/* ERET */
sprintf(insn_buf,"eret\n"); break;
default:
sprintf(insn_buf,".word\t0x%08x\n",opcode);
}
break;
default:
sprintf(insn_buf,".word\t0x%08x\n",opcode);
}
}
else if(cn==1){
dis_cp1(rs,rt,rd,sa,func,pc);
}
else if(cn==2){/* COP2 */
switch(rs&0xf){
case 000:/* MF */
sprintf(insn_buf,"mfc2\tr%d,r%d\n",rt,rd&0x1f);
break;
case 001:/* DMF */
sprintf(insn_buf,"dmfc2\tr%d,r%d\n",rt,rd&0x1f);
break;
case 002:/* CF */
sprintf(insn_buf,"cfc2\tr%d,r%d\n",rt,rd&0x1f);
break;
case 004:/* MT */
sprintf(insn_buf,"mtc2\tr%d,r%d\n",rt,rd&0x1f);
break;
case 005:/* DMT */
sprintf(insn_buf,"dmtc2\tr%d,r%d\n",rt,rd&0x1f);
break;
case 006:/* CT */
sprintf(insn_buf,"ctc2\tr%d,r%d\n",rt,rd&0x1f);
break;
case 010:/* BC */
if(rt==0)
sprintf(insn_buf,"bc2f\t0x%08x\n",(long)temppc);
else if(rt==1)
sprintf(insn_buf,"bc2t\t0x%08x\n",(long)temppc);
else if(rt==2)
sprintf(insn_buf,"bc2fl\t0x%08x\n",(long)temppc);
else if(rt==3)
sprintf(insn_buf,"bc2tl\t0x%08x\n",(long)temppc);
else
sprintf(insn_buf,".word\t0x%08x\n",(long)opcode);
break;
default:
sprintf(insn_buf,".word\t0x%08x\n",(long)opcode);
}
}
else if(cn==3){/* COP3 */
switch(rs&0xf){
case 000:/* MF */
sprintf(insn_buf,"mfc3\tr%d,r%d\n",rt,rd&0x1f);
break;
case 001:/* DMF */
sprintf(insn_buf,"dmfc3\tr%d,r%d\n",rt,rd&0x1f);
break;
case 002:/* CF */
sprintf(insn_buf,"cfc3\tr%d,r%d\n",rt,rd&0x1f);
break;
case 004:/* MT */
sprintf(insn_buf,"mtc3\tr%d,r%d\n",rt,rd&0x1f);
break;
case 005:/* DMT */
sprintf(insn_buf,"dmtc3\tr%d,r%d\n",rt,rd&0x1f);
break;
case 006:/* CT */
sprintf(insn_buf,"ctc3\tr%d,r%d\n",rt,rd&0x1f);
break;
case 010:/* BC */
if(rt==0)
sprintf(insn_buf,"bc3f\t0x%08x\n",(long)temppc);
else if(rt==1)
sprintf(insn_buf,"bc3t\t0x%08x\n",(long)temppc);
else if(rt==2)
sprintf(insn_buf,"bc3fl\t0x%08x\n",(long)temppc);
else if(rt==3)
sprintf(insn_buf,"bc3tl\t0x%08x\n",(long)temppc);
else
sprintf(insn_buf,".word\t0x%08x\n",(long)opcode);
break;
default:
sprintf(insn_buf,".word\t0x%08x\n",(long)opcode);
}
}
else {
sprintf(insn_buf,".word\t0x%08x\n",opcode);
}
}
static void dis_cache(int ca,int opr,int base,long offset,ulong pc)
{
static char *c[4]={"I","D","SI","SD"};
static char *operation;
switch(opr){
case 0:
if(ca==0||ca==2)
operation="Index_Inv";
else
operation="Index_Writeback_Inv";
break;
case 1:
operation="Index_Load_Tag";
break;
case 2:
operation="Index_Store_Tag";
break;
case 3:
operation="Create_Dirty";
break;
case 4:
operation="Hit_Inv";
break;
case 5:
if(ca==0)
operation="Fill";
else
operation="Hit_Writeback_Inv";
break;
case 6:
operation="Hit_Writeback";
break;
case 7:
operation="Hit_Set_Virtual";
break;
}
sprintf(insn_buf,"cache\t%s_%s,%d(%s)\n",
operation,
c[ca],
offset,
regn[base] );
}
static void dis_special2(int rs, int rt, int rd, int func)
{
switch(func){
case 000:/* MADD */
sprintf(insn_buf,"madd\t%s,%s\n",regn[rs],regn[rt]);
break;
case 001:/* MADDU */
sprintf(insn_buf,"maddu\t%s,%s\n",regn[rs],regn[rt]);
break;
case 002:/* MUL */
sprintf(insn_buf,"mul\t%s,%s,%s\n",regn[rd],regn[rs],regn[rt]);
break;
case 004:/* MSUB */
sprintf(insn_buf,"msub\t%s,%s\n",regn[rs],regn[rt]);
break;
case 005:/* MSUBU */
sprintf(insn_buf,"msubu\t%s,%s\n",regn[rs],regn[rt]);
break;
case 040:/* CLZ */
sprintf(insn_buf,"clz\t%s,%s\n",regn[rt],regn[rs]);
break;
case 041:/* CLO */
sprintf(insn_buf,"clo\t%s,%s\n",regn[rt],regn[rs]);
break;
case 044:/* DCLZ */
sprintf(insn_buf,"dclz\t%s,%s\n",regn[rt],regn[rs]);
break;
case 045:/* DCLO */
sprintf(insn_buf,"dclo\t%s,%s\n",regn[rt],regn[rs]);
break;
case 077:/* SSNOP */
sprintf(insn_buf,"ssnop\n");
break;
default:
sprintf(insn_buf,".word\t0x%08x\n",(long)opcode);
}
}
static void dis_mips(ulong insn,ulong pc)
{
int op,rs,rt,rd,sa,func,immd,targ;
ulong temppc;
if(insn==0){
printf("%08x %08x : nop\n",pc,opcode);
return;
}
op=(insn>>26)&0x3f;
rs=(insn>>21)&0x1f;
rt=(insn>>16)&0x1f;
rd=(insn>>11)&0x1f;
sa=(insn>> 6)&0x1f;
func=insn&0x3f;
immd=insn&0xffff;
targ=insn&0x3ffffff;
#if 0
printf("op=%02x rs=%02x rt=%02x rd=%02x sa=%02x func=%02x immd=%04x targ=%07x\n",
op,rs,rt,rd,sa,func,immd,targ);
#endif
switch(op){
case 000:/* SPECIAL */
dis_special(rs,rt,rd,sa,func,immd,targ,pc);
break;
case 001:/* BCOND */
dis_bcond(rs,rt,rd,sa,func,immd,targ,pc);
break;
case 002:/* J */
case 003:/* JAL */
temppc=(pc&0xf0000000)|(targ<<2);
sprintf(insn_buf,"%s\t0x%08x\n",jnam[op-2],(long)temppc);
break;
case 004:/* BEQ */
case 005:/* BNE */
case 006:/* BLEZ */
case 007:/* BGTZ */
if(immd&0x8000) temppc=0xfffc0000|(immd<<2);
else temppc=immd<<2;
temppc=(pc+4)+temppc;
sprintf(insn_buf,"%s\t%s,%s,0x%08x\n",bnam[op-4],regn[rs],regn[rt],(long)temppc);
break;
case 010:/* ADDI */
case 011:/* ADDIU */
case 012:/* SLTI */
case 013:/* SLTIU */
if(immd&0x8000) immd=0xffff0000|immd;
if(immd<0)
sprintf(insn_buf,"%s\t%s,%s,-0x%04x\n",inam[op-010],regn[rt],regn[rs],-immd);
else
sprintf(insn_buf,"%s\t%s,%s,0x%04x\n",inam[op-010],regn[rt],regn[rs],immd&0xffff);
break;
case 014:/* ANDI */
case 015:/* ORI */
case 016:/* XORI */
sprintf(insn_buf,"%s\t%s,%s,0x%04x\n",inam[op-010],regn[rt],regn[rs],immd&0xffff);
break;
case 017:/* LUI */
sprintf(insn_buf,"lui\t%s,0x%04x\n",regn[rt],immd&0xffff);
break;
case 020:/* COP0 */
case 021:/* COP1 */
case 022:/* COP2 */
dis_copz(op-020,rs,rt,rd,sa,func,immd,targ,pc);
break;
case 023:/* COP3 */
if(ty_mips==MIPS4)
dis_cop1x(rs,rt,rd,sa,func,immd,targ,pc);
else
dis_copz(op-020,rs,rt,rd,sa,func,immd,targ,pc);
break;
case 024:/* BEQL */
case 025:/* BNEL */
case 026:/* BLEZL */
case 027:/* BGTZL */
if(immd&0x8000) temppc=0xfffc0000|(immd<<2);
else temppc=immd<<2;
temppc=(pc+4)+temppc;
sprintf(insn_buf,"%sl\t%s,%s,0x%08x\n",bnam[op-024],regn[rs],regn[rt],(long)temppc);
break;
case 030:/* DADDI */
case 031:/* DADDU */
if(immd&0x8000) immd=0xffff0000|immd;
if(immd<0)
sprintf(insn_buf,"%s\t%s,%s,-0x%04x\n",
(op==030)? "daddi" : "daddiu",
regn[rt],regn[rs],-immd);
else
sprintf(insn_buf,"%s\t%s,%s,0x%04x\n",
(op==030)? "daddi" : "daddiu",
regn[rt],regn[rs],immd&0xffff);
break;
case 032:/* LDL */
case 033:/* LDR */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"%s\t%s,%d(%s)\n",
(op==032)? "ldl" : "ldr",
regn[rt],immd,regn[rs]);
break;
case 034:/* Special2 */
dis_special2(rs,rt,rd,func);
break;
case 035:/* JALX */
temppc=(pc&0xf0000000)|(targ<<2);
sprintf(insn_buf,"jalx\t0x%08x\n",(long)temppc);
break;
case 040:/* LB */
case 041:/* LH */
case 042:/* LWL */
case 043:/* LW */
case 044:/* LBU */
case 045:/* LHU */
case 046:/* LWR */
case 047:/* LWU */
case 050:/* SB */
case 051:/* SH */
case 052:/* SWL */
case 053:/* SW */
case 054:/* SDL */
case 055:/* SDR */
case 056:/* SWR */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"%s\t%s,%d(%s)\n",lsnam[op-040],regn[rt],immd,regn[rs]);
break;
case 057:/* CACHE */
if(immd&0x8000) immd=0xffff0000|immd;
dis_cache(rt&3/*cache*/,
(rt>>2)/*operation*/,
rs/*base*/,
immd,
pc);
break;
case 060:/* LCW0 */
if(immd&0x8000) immd=0xffff0000|immd;
if(ty_mips==MIPS1)
sprintf(insn_buf,"lwc0\t%s,%d(%s)\n",
cregn[rt],immd,regn[rs]);
else
sprintf(insn_buf,"ll\t%s,%d(%s)\n",
regn[rt],immd,regn[rs]);
break;
case 061:/* LCW1 */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"lwc%d\tfp%d,%d(%s)\n",op-060,rt&0x1f,immd,regn[rs]);
break;
case 062:/* LCW2 */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"lwc%d\tr%d,%d(%s)\n",op-060,rt,immd,regn[rs]);
break;
case 063:/* LCW3 */
if(immd&0x8000) immd=0xffff0000|immd;
if(ty_mips==MIPS4){ /* PREF */
switch(rt){
case 0:
case 1:
case 4:
case 5:
case 6:
case 7:
case 25:
sprintf(insn_buf,"pref\t%s,%d(%s)\n",pref_hint[rt],immd,regn[rs]);
break;
default:
sprintf(insn_buf,"pref\t%d,%d(%s)\n",rt,immd,regn[rs]);
}
}
else{
sprintf(insn_buf,"lwc%d\tr%d,%d(%s)\n",op-060,rt,immd,regn[rs]);
}
break;
case 064:/* LLD */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"lld\t%s,%d(%s)\n",regn[rt],immd,regn[rs]);
break;
case 065:/* LCD1 */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"ldc%d\tfp%d,%d(%s)\n",op-064,rt&0x1f,immd,regn[rs]);
break;
case 066:/* LCD2 */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"ldc%d\tr%d,%d(%s)\n",op-064,rt,immd,regn[rs]);
break;
case 067:/* LD */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"ld\t%s,%d(%s)\n",regn[rt],immd,regn[rs]);
break;
case 070:/* SCW0 */
if(immd&0x8000) immd=0xffff0000|immd;
if(ty_mips==MIPS1)
sprintf(insn_buf,"swc0\t%s,%d(%s)\n",
cregn[rt],immd,regn[rs]);
else
sprintf(insn_buf,"sc\t%s,%d(%s)\n",
regn[rt],immd,regn[rs]);
break;
case 071:/* SCW1 */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"swc%d\tfp%d,%d(%s)\n",op-070,rt&0x1f,immd,regn[rs]);
break;
case 072:/* SCW2 */
case 073:/* SCW3 */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"swc%d\tr%d,%d(%s)\n",op-070,rt,immd,regn[rs]);
break;
case 074:/* SCD */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"scd\t%s,%d(%s)\n",
regn[rt],immd,regn[rs]);
break;
case 075:/* SCD1 */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"sdc%d\tfp%d,%d(%s)\n",op-074,rt&0x1f,immd,regn[rs]);
break;
case 076:/* SCD2 */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"sdc%d\tr%d,%d(%s)\n",op-074,rt,immd,regn[rs]);
break;
case 077:/* SD */
if(immd&0x8000) immd=0xffff0000|immd;
sprintf(insn_buf,"sd\t%s,%d(%s)\n",regn[rt],immd,regn[rs]);
break;
default:
sprintf(insn_buf,".word\t0x%08x\n",opcode);
}
printf("%08x %08x : %s",pc,opcode,insn_buf);
}
/*****************************************************************/
static int dis_jal_flag = 0;
static int dis_extend_flag = 0;
static ulong dis_extend_inst;
static int mips16_reg_get(int reg)
{
if(reg==0) return 16;
if(reg==1) return 17;
return reg;
}
static void dis_mips16_RR(ulong decRR, ulong decRX, ulong decRY, ulong decSA, ulong insn)
{
switch(decRR){
case 000:/* j(al)r */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
switch(decRY&0x7){
case 0:/* jr rx */
sprintf(insn_buf,"jr\tr%d\n",decRX);
break;
case 1:
if(decRX==16)
sprintf(insn_buf,"jr\tra\n");
else
sprintf(insn_buf,"reserved(RR)\n");
break;
case 2:
sprintf(insn_buf,"jalr\tra,r%d\n",decRX);
break;
default:
sprintf(insn_buf,"reserved(RR)\n");
}
}
break;
case 001:
sprintf(insn_buf,"reserved(RR)\n");
break;
case 002:/* slt */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"slt\tr%d,r%d\n",decRX,decRY);
}
break;
case 003:/* sltu */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"sltu\tr%d,r%d\n",decRX,decRY);
}
break;
case 004:/* sllv */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"sllv\tr%d,r%d\n",decRY,decRX);
}
break;
case 005:/* break */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"break\t0x%x\n",((decRX&7)<<3)|(decRY&7));
}
break;
case 006:/* srlv */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"srlv\tr%d,r%d\n",decRY,decRX);
}
break;
case 007:/* srav */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"srav\tr%d,r%d\n",decRY,decRX);
}
break;
case 010:/* dsrl */
if(dis_extend_flag){
decSA=(insn&0x20)|((insn>>6)&0x1f);
}
else{
decRX &= 7;
if(decRX==0)
decSA=8;
else
decSA=decRX;
}
sprintf(insn_buf,"dsrl\tr%d,%d\n",decRY,decSA);
break;
case 011:/* syscall */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"syscall\t0x%x\n",((decRX&7)<<3)|(decRY&7));
}
break;
case 012:/* cmp */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"cmp\tr%d,r%d\n",decRX,decRY);
}
break;
case 013:/* neg */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"neg\tr%d,r%d\n",decRX,decRY);
}
break;
case 014:/* and */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"and\tr%d,r%d\n",decRX,decRY);
}
break;
case 015:/* or */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"or\tr%d,r%d\n",decRX,decRY);
}
break;
case 016:/* xor */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"xor\tr%d,r%d\n",decRX,decRY);
}
break;
case 017:/* not */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"not\tr%d,r%d\n",decRX,decRY);
}
break;
case 020:/* mfhi */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
if(decRY&7)
sprintf(insn_buf,"reserved(RR)\n");
else
sprintf(insn_buf,"mfhi\tr%d\n",decRX);
}
break;
case 021:
sprintf(insn_buf,"reserved(RR)\n");
break;
case 022:/* mflo */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
if(decRY&7)
sprintf(insn_buf,"reserved(RR)\n");
else
sprintf(insn_buf,"mflo\tr%d\n",decRX);
}
break;
case 023:/* dsra */
if(dis_extend_flag){
decSA=(insn&0x20)|((insn>>6)&0x1f);
}
else{
decRX &= 7;
if(decRX==0)
decSA=8;
else
decSA=decRX;
}
sprintf(insn_buf,"dsra\tr%d,%d\n",decRY,decSA);
break;
case 024:/* dsllv */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"dsllv\tr%d,r%d\n",decRY,decRX);
}
break;
case 025:
sprintf(insn_buf,"reserved(RR)\n");
break;
case 026:/* dsrlv */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"dsrlv\tr%d,r%d\n",decRY,decRX);
}
break;
case 027:/* dsrav */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"dsrav\tr%d,r%d\n",decRY,decRX);
}
break;
case 030:/* mult */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"mult\tr%d,r%d\n",decRX,decRY);
}
break;
case 031:/* multu */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"multu\tr%d,r%d\n",decRX,decRY);
}
break;
case 032:/* div */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"div\tr%d,r%d\n",decRX,decRY);
}
break;
case 033:/* divu */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"divu\tr%d,r%d\n",decRX,decRY);
}
break;
case 034:/* dmult */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"dmult\tr%d,r%d\n",decRX,decRY);
}
break;
case 035:/* dmultu */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"dmultu\tr%d,r%d\n",decRX,decRY);
}
break;
case 036:/* ddiv */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"ddiv\tr%d,r%d\n",decRX,decRY);
}
break;
case 037:/* ddivu */
if(dis_extend_flag){
sprintf(insn_buf,"reserved(RR)\n");
}
else{
sprintf(insn_buf,"ddivu\tr%d,r%d\n",decRX,decRY);
}
break;
}
}
static void dis_mips16_extend( ulong insn, ulong pc)
{
ulong decOP,decRX,decRY,decRZ,decSA,decFUNC,decRR,decIMMD,decIMMD5,decTARG,decCODE;
ulong temppc;
insn = (insn<<16)|dis_extend_inst;
/*printf("insn32=%08x\n",insn);*/
decOP = (insn>>(11+16))&0x1f;
decRX =mips16_reg_get((insn>>( 8+16))&0x7);
decRY =mips16_reg_get((insn>>( 5+16))&0x7);
decRZ =mips16_reg_get((insn>>( 2+16))&0x7);
decSA = (insn>>( 2+16))&0x7;
decFUNC = (insn>> 16 )&0x3;
decRR = (insn>> 16 )&0x1f;
decIMMD5= (insn>> 16 )&0x1f;
decSA = (insn&0x400000)? (0x20|decSA):decSA;
decIMMD = ((insn&0x1f)<<11)|(insn&0x7e0)|decIMMD5;
decTARG = decIMMD;
decCODE = (insn>>( 5+16))&0x1f;
if(dis_jal_flag)
decOP = 003;
switch(decOP){
case 000:/* addiusp */
if(decIMMD&0x8000)
sprintf(insn_buf,"addiu\tr%d,sp,-0x%04x\n",decRX,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"addiu\tr%d,sp,0x%04x\n",decRX,decIMMD);
break;
case 001:/* addiupc */
if(decIMMD&0x8000)
sprintf(insn_buf,"addiu\tr%d,pc,-0x%04x\n",decRX,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"addiu\tr%d,pc,0x%04x\n",decRX,decIMMD);
break;
case 002:/* b */
if(decTARG&0x8000)
temppc=(0xffff0000|decTARG)<<1;
else temppc=decTARG<<1;
temppc+=2+pc;
sprintf(insn_buf,"b\t0x%08x\n",temppc);
break;
case 003:/* jal(x) */
temppc=(pc&0xf0000000)|
((((insn&0x1f)<<21)|((insn&0x3e0)<<11)|((insn>>16)&0xffff))
<<2);
if(insn&0x400)/* jalx */
sprintf(insn_buf,"jalx\t0x%08x\n",temppc);
else /* jal */
sprintf(insn_buf,"jal\t0x%08x\n",temppc);
dis_jal_flag=0;
break;
case 004:/* beqz */
if(decTARG&0x8000)
temppc=(0xffff0000|decTARG)<<1;
else temppc=decTARG<<1;
temppc+=2+pc;
sprintf(insn_buf,"beqz\tr%d,0x%08x\n",decRX,temppc);
break;
case 005:/* bnez */
if(decTARG&0x8000)
temppc=(0xffff0000|decTARG)<<1;
else temppc=decTARG<<1;
temppc+=2+pc;
sprintf(insn_buf,"bnez\tr%d,0x%08x\n",decRX,temppc);
break;
case 006:/* SHIFT */
decSA=((insn>>6)&0x1f)|((insn)&0x20);
switch(decFUNC){
case 0:/* sll */
sprintf(insn_buf,"sll\tr%d,r%d,%d\n",decRX,decRY,decSA);
break;
case 1:/* dsll */
sprintf(insn_buf,"dsll\tr%d,r%d,%d\n",decRX,decRY,decSA);
break;
case 2:/* srl */
sprintf(insn_buf,"srl\tr%d,r%d,%d\n",decRX,decRY,decSA);
break;
default:/* sra */
sprintf(insn_buf,"sra\tr%d,r%d,%d\n",decRX,decRY,decSA);
}
break;
case 007:/* ld */
if(decIMMD&0x8000)
sprintf(insn_buf,"ld\tr%d,-0x%04x(r%d)\n",decRY,-(long)(0xffff0000|decIMMD),decRX);
else
sprintf(insn_buf,"ld\tr%d,0x%04x(r%d)\n",decRY,decIMMD,decRX);
break;
case 010:/* RRI-A */
decIMMD=((insn&0xf)<<11)|(insn&0x7f0)|((insn>>16)&0xf);
if(decRR&0x10){/* daddiu */
if(decIMMD&0x4000)
sprintf(insn_buf,"daddiu\tr%d,r%d,-0x%x\n",decRY,decRX,-(long)(0xffff8000|decIMMD));
else
sprintf(insn_buf,"daddiu\tr%d,r%d,0x%x\n",decRY,decRX,decIMMD);
}
else{/* addiu */
if(decIMMD&0x4000)
sprintf(insn_buf,"addiu\tr%d,r%d,-0x%x\n",decRY,decRX,-(long)(0xffff8000|decIMMD));
else
sprintf(insn_buf,"addiu\tr%d,r%d,0x%x\n",decRY,decRX,decIMMD);
}
break;
case 011:/* addiu8 */
if(decIMMD&0x8000)
sprintf(insn_buf,"addiu\tr%d,-0x%04x\n",decRX,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"addiu\tr%d,0x%04x\n",decRX,decIMMD);
break;
case 012:/* slti */
if(decIMMD&0x8000)
sprintf(insn_buf,"slti\tr%d,-0x%04x\n",decRX,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"slti\tr%d,0x%04x\n",decRX,decIMMD);
break;
case 013:/* sltiu */
if(decIMMD&0x8000)
sprintf(insn_buf,"sltiu\tr%d,-0x%04x\n",decRX,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"sltiu\tr%d,0x%04x\n",decRX,decIMMD);
break;
case 014:/* l8 */
switch((insn>>(8+16))&7){
case 0:/* bteqz */
if(decTARG&0x8000)
temppc=(0xffff0000|decTARG)<<1;
else
temppc=decTARG<<1;
temppc+=2+pc;
sprintf(insn_buf,"bteqz\t0x%08x\n",temppc);
break;
case 1:/* btnez */
if(decTARG&0x8000)
temppc=(0xffff0000|decTARG)<<1;
else
temppc=decTARG<<1;
temppc+=2+pc;
sprintf(insn_buf,"btnez\t0x%08x\n",temppc);
break;
case 2:/* swrasp */
if(decIMMD&0x8000)
sprintf(insn_buf,"sw\tra,-0x%04x(sp)\n",-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"sw\tra,0x%04x(sp)\n",decIMMD);
break;
case 3:/* adjsp */
if(decIMMD&0x8000)
sprintf(insn_buf,"addiu\tsp,-0x%04x\n",-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"addiu\tsp,0x%04x\n",decIMMD);
break;
case 4:
sprintf(insn_buf,"reserved(I8)\n");
break;
case 5:/* mov32r */
sprintf(insn_buf,"reserved(I8)\n");
break;
case 6:
sprintf(insn_buf,"reserved(I8)\n");
break;
default:/* movr32 */
sprintf(insn_buf,"reserved(I8)\n");
}
break;
case 015:/* li */
sprintf(insn_buf,"li\tr%d,0x%04x\n",decRX,decIMMD);
break;
case 016:/* cmpi */
if(decIMMD&0x8000)
sprintf(insn_buf,"cmpi\tr%d,-0x%04x\n",decRX,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"cmpi\tr%d,0x%04x\n",decRX,decIMMD);
break;
case 017:/* sd */
if(decIMMD&0x8000)
sprintf(insn_buf,"sd\tr%d,-0x%04x(r%d)\n",decRY,-(long)(0xffff0000|decIMMD),decRX);
else
sprintf(insn_buf,"sd\tr%d,0x%04x(r%d)\n",decRY,decIMMD,decRX);
break;
case 020:/* lb */
if(decIMMD&0x8000)
sprintf(insn_buf,"lb\tr%d,-0x%04x(r%d)\n",decRY,-(long)(0xffff0000|decIMMD),decRX);
else
sprintf(insn_buf,"lb\tr%d,0x%04x(r%d)\n",decRY,decIMMD,decRX);
break;
case 021:/* lh */
if(decIMMD&0x8000)
sprintf(insn_buf,"lh\tr%d,-0x%04x(r%d)\n",decRY,-(long)(0xffff0000|decIMMD),decRX);
else
sprintf(insn_buf,"lh\tr%d,0x%04x(r%d)\n",decRY,decIMMD,decRX);
break;
case 022:/* lwsp */
if(decIMMD&0x8000)
sprintf(insn_buf,"lw\tr%d,-0x%04x(sp)\n",decRX,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"lw\tr%d,0x%04x(sp)\n",decRX,decIMMD);
break;
case 023:/* lw */
if(decIMMD&0x8000)
sprintf(insn_buf,"lw\tr%d,-0x%04x(r%d)\n",decRY,-(long)(0xffff0000|decIMMD),decRX);
else
sprintf(insn_buf,"lw\tr%d,0x%04x(r%d)\n",decRY,decIMMD,decRX);
break;
case 024:/* lbu */
if(decIMMD&0x8000)
sprintf(insn_buf,"lbu\tr%d,-0x%04x(r%d)\n",decRY,-(long)(0xffff0000|decIMMD),decRX);
else
sprintf(insn_buf,"lbu\tr%d,0x%04x(r%d)\n",decRY,decIMMD,decRX);
break;
case 025:/* lhu */
if(decIMMD&0x8000)
sprintf(insn_buf,"lhu\tr%d,-0x%04x(r%d)\n",decRY,-(long)(0xffff0000|decIMMD),decRX);
else
sprintf(insn_buf,"lhu\tr%d,0x%04x(r%d)\n",decRY,decIMMD,decRX);
break;
case 026:/* lwpc */
if(decIMMD&0x8000)
sprintf(insn_buf,"lw\tr%d,-0x%04x(pc)\n",decRX,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"lw\tr%d,0x%04x(pc)\n",decRX,decIMMD);
break;
case 027:/* lwu */
if(decIMMD&0x8000)
sprintf(insn_buf,"lwu\tr%d,-0x%04x(r%d)\n",decRY,-(long)(0xffff0000|decIMMD),decRX);
else
sprintf(insn_buf,"lwu\tr%d,0x%04x(r%d)\n",decRY,decIMMD,decRX);
break;
case 030:/* sb */
if(decIMMD&0x8000)
sprintf(insn_buf,"sb\tr%d,-0x%04x(r%d)\n",decRY,-(long)(0xffff0000|decIMMD),decRX);
else
sprintf(insn_buf,"sb\tr%d,0x%04x(r%d)\n",decRY,decIMMD,decRX);
break;
case 031:/* sh */
if(decIMMD&0x8000)
sprintf(insn_buf,"sh\tr%d,-0x%04x(r%d)\n",decRY,-(long)(0xffff0000|decIMMD),decRX);
else
sprintf(insn_buf,"sh\tr%d,0x%04x(r%d)\n",decRY,decIMMD,decRX);
break;
case 032:/* swsp */
if(decIMMD&0x8000)
sprintf(insn_buf,"sw\tr%d,-0x%04x(sp)\n",decRX,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"sw\tr%d,0x%04x(sp)\n",decRX,decIMMD);
break;
case 033:/* sw */
if(decIMMD&0x8000)
sprintf(insn_buf,"sw\tr%d,-0x%04x(r%d)\n",decRY,-(long)(0xffff0000|decIMMD),decRX);
else
sprintf(insn_buf,"sw\tr%d,0x%04x(r%d)\n",decRY,decIMMD,decRX);
break;
case 034:/* RRR */
sprintf(insn_buf,"reserved(RRR)\n");
break;
case 035:/* RR */
dis_mips16_RR(decRR,decRX,decRY,decSA,insn);
break;
case 036:/* extend */
sprintf(insn_buf,"reserved(EXTEND)\n");
break;
case 037:/* I64 */
switch(decRX&7){
case 0:
if(decIMMD&0x8000)
sprintf(insn_buf,"ld\tr%d,-0x%04x(sp)\n",decRY,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"ld\tr%d,0x%04x(sp)\n",decRY,decIMMD);
break;
case 1:
if(decIMMD&0x8000)
sprintf(insn_buf,"sd\tr%d,-0x%04x(sp)\n",decRY,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"sd\tr%d,0x%04x(sp)\n",decRY,decIMMD);
break;
case 2:
if(decIMMD&0x8000)
sprintf(insn_buf,"sd\tra,-0x%04x(sp)\n",-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"sd\tra,0x%04x(sp)\n",decIMMD);
break;
case 3:
if(decIMMD&0x8000)
sprintf(insn_buf,"daddiu\tsp,-0x%04x\n",-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"daddiu\tsp,0x%04x\n",decIMMD);
break;
case 4:
if(decIMMD&0x8000)
sprintf(insn_buf,"ld\tr%d,-0x%04x(pc)\n",decRY,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"ld\tr%d,0x%04x(pc)\n",decRY,decIMMD);
break;
case 5:
if(decIMMD&0x8000)
sprintf(insn_buf,"daddiu\tr%d,-0x%04x\n",decRY,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"daddiu\tr%d,0x%04x\n",decRY,decIMMD);
break;
case 6:
if(decIMMD&0x8000)
sprintf(insn_buf,"daddiu\tr%d,pc,-0x%04x\n",decRY,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"daddiu\tr%d,pc,0x%04x\n",decRY,decIMMD);
break;
default:
if(decIMMD&0x8000)
sprintf(insn_buf,"daddiu\tr%d,sp,-0x%04x\n",decRY,-(long)(0xffff0000|decIMMD));
else
sprintf(insn_buf,"daddiu\tr%d,sp,0x%04x\n",decRY,decIMMD);
break;
}
break;
}
}
static void dis_mips16( ulong insn, ulong pc)
{
ulong decOP,decRX,decRY,decRZ,decSA,decFUNC,decRR,decIMMD,decIMMD5,decTARG,decCODE;
ulong temppc;
decOP = (insn>>11)&0x1f;
decRX =mips16_reg_get((insn>> 8)&0x7);
decRY =mips16_reg_get((insn>> 5)&0x7);
decRZ =mips16_reg_get((insn>> 2)&0x7);
decSA = (insn>> 2)&0x7;
decFUNC = insn &0x3;
decRR = insn &0x1f;
decIMMD = insn &0xff;
decIMMD5= insn &0x1f;
decTARG = insn &0x7ff;
decCODE = (insn>> 5)&0x1f;
/* printf("DIS_mips16\n"); */
if(dis_extend_flag){
dis_mips16_extend(insn,pc);
dis_extend_flag = 0;
}
else{
switch(decOP){
case 000:/* addiusp */
sprintf(insn_buf,"addiu\tr%d,sp,0x%03x\n",decRX,decIMMD<<2);
break;
case 001:/* addiupc */
sprintf(insn_buf,"addiu\tr%d,pc,0x%03x\n",decRX,decIMMD<<2);
break;
case 002:/* b */
if(decTARG&0x400)
temppc=(0xfffff800|decTARG)<<1;
else
temppc=decTARG<<1;
temppc+=2+pc;
sprintf(insn_buf,"b\t0x%08x\n",temppc);
break;
case 003:/* jal(x) */
sprintf(insn_buf,"jal(x)\n");
dis_extend_flag=1;
dis_extend_inst=insn;
dis_jal_flag=1;
break;
case 004:/* beqz */
if(decIMMD&0x80)
temppc=(0xffffff00|decIMMD)<<1;
else
temppc=decIMMD<<1;
temppc+=2+pc;
sprintf(insn_buf,"beqz\tr%d,0x%08x\n",decRX,temppc);
break;
case 005:/* bnez */
if(decIMMD&0x80)
temppc=(0xffffff00|decIMMD)<<1;
else
temppc=decIMMD<<1;
temppc+=2+pc;
sprintf(insn_buf,"bnez\tr%d,0x%08x\n",decRX,temppc);
break;
case 006:/* SHIFT */
if(decSA==0)
decSA = 8;
switch(decFUNC){
case 0:/* sll */
sprintf(insn_buf,"sll\tr%d,r%d,%d\n",decRX,decRY,decSA);
break;
case 1:/* dsll */
sprintf(insn_buf,"dsll\tr%d,r%d,%d\n",decRX,decRY,decSA);
break;
case 2:/* srl */
sprintf(insn_buf,"srl\tr%d,r%d,%d\n",decRX,decRY,decSA);
break;
default:/* sra */
sprintf(insn_buf,"sra\tr%d,r%d,%d\n",decRX,decRY,decSA);
}
break;
case 007:/* ld */
sprintf(insn_buf,"ld\tr%d,0x%02x(r%d)\n",decRY,decIMMD5<<3,decRX);
break;
case 010:/* RRI-A */
if(insn&0x10){/* daddiu */
if(insn&0x8)
sprintf(insn_buf,"daddiu\tr%d,r%d,-0x%x\n",decRY,decRX,-(long)(0xfffffff0|(insn&0xf)));
else
sprintf(insn_buf,"daddiu\tr%d,r%d,0x%x\n",decRY,decRX,(insn&0xf));
}
else{/* addiu */
if(insn&0x8)
sprintf(insn_buf,"addiu\tr%d,r%d,-0x%x\n",decRY,decRX,-(long)(0xfffffff0|(insn&0xf)));
else
sprintf(insn_buf,"addiu\tr%d,r%d,0x%x\n",decRY,decRX,(insn&0xf));
}
break;
case 011:/* addiu8 */
if(decIMMD&0x80)
sprintf(insn_buf,"addiu\tr%d,-0x%02x\n",decRX,-(long)(0xffffff00|decIMMD));
else
sprintf(insn_buf,"addiu\tr%d,0x%02x\n",decRX,decIMMD);
break;
case 012:/* slti */
sprintf(insn_buf,"slti\tr%d,0x%02x\n",decRX,decIMMD);
break;
case 013:/* sltiu */
sprintf(insn_buf,"sltiu\tr%d,0x%02x\n",decRX,decIMMD);
break;
case 014:/* l8 */
switch((insn>>8)&7){
case 0:/* bteqz */
if(decIMMD&0x80)
temppc=(0xffffff00|decIMMD)<<1;
else
temppc=decIMMD<<1;
temppc+=2+pc;
sprintf(insn_buf,"bteqz\t0x%08x\n",temppc);
break;
case 1:/* btnez */
if(decIMMD&0x80)
temppc=(0xffffff00|decIMMD)<<1;
else
temppc=decIMMD<<1;
temppc+=2+pc;
sprintf(insn_buf,"btnez\t0x%08x\n",temppc);
break;
case 2:/* swrasp */
sprintf(insn_buf,"sw\tra,0x%02x(sp)\n",decIMMD<<2);
break;
case 3:/* adjsp */
if(decIMMD&0x80)
sprintf(insn_buf,"addiu\tsp,-0x%03x\n",-(long)((0xffffff00|decIMMD)<<3));
else
sprintf(insn_buf,"addiu\tsp,0x%03x\n",decIMMD<<3);
break;
case 4:
sprintf(insn_buf,"reserved(I8)\n");
break;
case 5:/* mov32r */
sprintf(insn_buf,"move\tr%d,r%d\n",((decIMMD>>5)&7)|(decIMMD&0x18),
mips16_reg_get(decIMMD&0x7));
break;
case 6:
sprintf(insn_buf,"reserved(I8)\n");
break;
default:/* movr32 */
sprintf(insn_buf,"move\tr%d,r%d\n",decRY,decIMMD5);
}
break;
case 015:/* li */
sprintf(insn_buf,"li\tr%d,0x%02x\n",decRX,decIMMD);
break;
case 016:/* cmpi */
sprintf(insn_buf,"cmpi\tr%d,0x%02x\n",decRX,decIMMD);
break;
case 017:/* sd */
sprintf(insn_buf,"sd\tr%d,0x%02x(r%d)\n",decRY,decIMMD5<<3,decRX);
break;
case 020:/* lb */
sprintf(insn_buf,"lb\tr%d,0x%02x(r%d)\n",decRY,decIMMD5,decRX);
break;
case 021:/* lh */
sprintf(insn_buf,"lh\tr%d,0x%02x(r%d)\n",decRY,decIMMD5<<1,decRX);
break;
case 022:/* lwsp */
sprintf(insn_buf,"lw\tr%d,0x%02x(sp)\n",decRX,decIMMD<<2);
break;
case 023:/* lw */
sprintf(insn_buf,"lw\tr%d,0x%02x(r%d)\n",decRY,decIMMD5<<2,decRX);
break;
case 024:/* lbu */
sprintf(insn_buf,"lbu\tr%d,0x%02x(r%d)\n",decRY,decIMMD5,decRX);
break;
case 025:/* lhu */
sprintf(insn_buf,"lhu\tr%d,0x%02x(r%d)\n",decRY,decIMMD5<<1,decRX);
break;
case 026:/* lwpc */
sprintf(insn_buf,"lw\tr%d,0x%02x(pc)\n",decRX,decIMMD<<2);
break;
case 027:/* lwu */
sprintf(insn_buf,"lwu\tr%d,0x%02x(r%d)\n",decRY,decIMMD5<<2,decRX);
break;
case 030:/* sb */
sprintf(insn_buf,"sb\tr%d,0x%02x(r%d)\n",decRY,decIMMD5,decRX);
break;
case 031:/* sh */
sprintf(insn_buf,"sh\tr%d,0x%02x(r%d)\n",decRY,decIMMD5<<1,decRX);
break;
case 032:/* swsp */
sprintf(insn_buf,"sw\tr%d,0x%02x(sp)\n",decRX,decIMMD<<2);
break;
case 033:/* sw */
sprintf(insn_buf,"sw\tr%d,0x%02x(r%d)\n",decRY,decIMMD5<<2,decRX);
break;
case 034:/* RRR */
switch(decFUNC){
case 0:/* daddu */
sprintf(insn_buf,"daddu\tr%d,r%d,r%d\n",decRZ,decRX,decRY);
break;
case 1:/* addu */
sprintf(insn_buf,"addu\tr%d,r%d,r%d\n",decRZ,decRX,decRY);
break;
case 2:/* dsubu */
sprintf(insn_buf,"dsubu\tr%d,r%d,r%d\n",decRZ,decRX,decRY);
break;
default:/* subu */
sprintf(insn_buf,"subu\tr%d,r%d,r%d\n",decRZ,decRX,decRY);
}
break;
case 035:/* RR */
dis_mips16_RR(decRR,decRX,decRY,decSA,insn);
break;
case 036:/* extend */
dis_extend_flag = 1;
dis_extend_inst = insn;
sprintf(insn_buf,"extend\n");
break;
case 037:/* I64 */
switch((insn>>8)&7){
case 0:
sprintf(insn_buf,"ld\tr%d,0x%02x(sp)\n",decRY,decIMMD5<<3);
break;
case 1:
sprintf(insn_buf,"sd\tr%d,0x%02x(sp)\n",decRY,decIMMD5<<3);
break;
case 2:
sprintf(insn_buf,"sd\tra,0x%03x(sp)\n",decIMMD<<3);
break;
case 3:
if(decIMMD&0x80)
sprintf(insn_buf,"daddiu\tsp,-0x%03x\n",-(long)((0xffffff00|decIMMD)<<3));
else
sprintf(insn_buf,"daddiu\tsp,0x%03x\n",decIMMD<<3);
break;
case 4:
sprintf(insn_buf,"ld\tr%d,0x%02x(pc)\n",decRY,decIMMD5<<3);
break;
case 5:
if(decIMMD5&0x10)
sprintf(insn_buf,"daddiu\tr%d,-0x%x\n",decRY,-(long)(0xffffffe0|decIMMD5));
else
sprintf(insn_buf,"daddiu\tr%d,0x%x\n",decRY,decIMMD5);
break;
case 6:
sprintf(insn_buf,"daddiu\tr%d,pc,0x%02x\n",decRY,decIMMD5<<2);
break;
default:
sprintf(insn_buf,"daddiu\tr%d,sp,0x%02x\n",decRY,decIMMD5<<2);
}
break;
}
}
printf("%08x %04x : %s",pc,opcode,insn_buf);
}